
import grpc
import vad_pb2
import vad_pb2_grpc
import numpy as np

def generate_audio_chunks(file_path, chunk_size=512):
    with open(file_path, 'rb') as f:
        while True:
            chunk = f.read(chunk_size * 2)  # 16-bit PCM, 2 bytes per sample
            if len(chunk) < chunk_size * 2:
                break
            yield vad_pb2.AudioChunk(audio_data=chunk, session_id="testessin_1")

def run_stream_vad(file_path):
    try:
        with grpc.insecure_channel("localhost:50052") as channel:
            stub = vad_pb2_grpc.VADServiceStub(channel)
            audio_chunks = generate_audio_chunks(file_path)
            # print("Received audio chunks:", audio_chunks)
            # with open(file_path, 'rb') as f:
            #     while True:
            #         chunk = f.read(1024)  # 16-bit PCM, 2 bytes per sample
            #         if len(chunk) < 1024:
            #             break
            #         yield stub.StreamVAD(vad_pb2.AudioChunk(chunk, session_id="test_session"))

            responses = stub.StreamVAD(audio_chunks)
            # if responses:
                # print(responses)
            for response in responses:
                   print("Received timestamps:", response.timestamps)
    except grpc.RpcError as e:
        print(f"RPC failed: {e.code()}: {e.details()}")

if __name__ == "__main__":
    run_stream_vad("test.pcm")  # 替换为你的 PCM 文件路径
    
    
# import grpc
# import vad_pb2
# import vad_pb2_grpc
# import numpy as np
# import base64



# def generate_audio_chunks(file_path, chunk_size=512, sample_rate=16000):
#     with open(file_path, 'rb') as f:
#         while True:
#             pcm_data = f.read(chunk_size * 2)  # 16位PCM，每个样本2字节
#             if not pcm_data:
#                 break
#             yield vad_pb2.AudioChunk(audio_data=pcm_data, sample_rate=sample_rate, session_id="test_session")

# def run_stream_vad(file_path):
#     try:
#         with grpc.insecure_channel("localhost:50052") as channel:
#             stub = vad_pb2_grpc.VADServiceStub(channel)
#             audio_chunks = generate_audio_chunks(file_path)
#             responses = stub.StreamVAD(audio_chunks)
#             for response in responses:
#                 print("Received timestamps:", response.timestamps)
#     except grpc.RpcError as e:
#         print(f"RPC failed: {e.code()}: {e.details()}")

# if __name__ == "__main__":
#     run_stream_vad("by.pcm")
# def generate_audio_chunks(file_path, chunk_size=1920, sample_rate=16000):
#     with open(file_path, 'rb') as f:
#         while True:
#             pcm_data = f.read(chunk_size)
#             if not pcm_data:
#                 break
#             yield vad_pb2.AudioChunk(audio_data=pcm_data, sample_rate=sample_rate, session_id="test_session")

# def read_pcm_file(file_path, chunk_size, sampling_rate):
#     """
#     Read PCM file in chunks
#     """
#     with open(file_path, 'rb') as f:
#         while True:
#             chunk = f.read(chunk_size * 2)  # 16-bit PCM, 2 bytes per sample
#             if not chunk:
#                 break
#             audio_int16 = np.frombuffer(chunk, dtype=np.int16)
#             audio_float32 = (audio_int16 / 32768.0).astype(np.float32)
#             yield vad_pb2.AudioChunk(audio_data=audio_float32, sample_rate=16000, session_id="test_session")
            

# def run_stream_vad(file_path):
#     try:
#         with grpc.insecure_channel("localhost:50052") as channel:
#             stub = vad_pb2_grpc.VADServiceStub(channel)
#             audio_chunks = read_pcm_file(file_path, 512, 16000)
#             responses = stub.StreamVAD(audio_chunks)
#             for response in responses:
#                 print("Received timestamps:", response.timestamps)
#     except grpc.RpcError as e:
#         print(f"RPC failed: {e.code()}: {e.details()}")


# if __name__ == "__main__":
#     run_stream_vad("by.pcm")  # 替换为你的 PCM 文件路径
# import grpc
# import vad_pb2
# import vad_pb2_grpc
# # import wave
# import numpy as np
# from typing import Generator
# import logging

# from silero_vad.model import load_silero_vad
# from silero_vad.utils_vad import (
#                           read_pcm,
#                           get_speech_timestamps)
# # 配置日志
# logging.basicConfig(
#     level=logging.INFO,
#     format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
# )
# logger = logging.getLogger("VADServer")


# def generate_audio_chunks(file_path, chunk_size=1920, session_id="default_session", sample_rate=16000):
#     with open(file_path, 'rb') as f:
#         while True:
#             pcm_data = f.read(chunk_size * 2 )  # 假设 16 位 PCM，每个样本 2 字节
#             if not pcm_data:
#                 break
#             # print("Received timestamps:", chunk_size)

#             yield vad_pb2.AudioChunk(
#                 audio_data=pcm_data,
#                 sample_rate=sample_rate,
#                 session_id=session_id
#             )
# def run_stream_vad(file_path, session_id="default_session"):
#     try:
#         with grpc.insecure_channel("localhost:50052") as channel:
#             stub = vad_pb2_grpc.VADServiceStub(channel)
#             audio_chunks = generate_audio_chunks(file_path, session_id=session_id)
#             # audio_chunks=read_audio('en_example0.wav', sampling_rate=16000)
#             responses = stub.StreamVAD(audio_chunks)
#             for response in responses:
#                 if response.timestamps:
#                     print("Received timestamps:", response.timestamps)
#                 else:
#                     print("No speech detected in this chunk.")
#     except grpc.RpcError as e:
#            print(f"RPC failed: {e.code()}: {e.details()}")

# if __name__ == '__main__':
#     # 测试流式 VAD
#     run_stream_vad('by.pcm', session_id="session_1")


# def generate_audio_chunks(file_path, chunk_size=1920, session_id="default_session"):
#     with wave.open(file_path, 'rb') as wf:
#         sample_rate = 16000
#         while True:
#             frames = wf.readframes(chunk_size)
#             if not frames:
#                 break
#             yield vad_pb2.AudioChunk(audio_data=frames, sample_rate=sample_rate, session_id=session_id)


# def generate_audio_chunks(file_path, chunk_size=1920, session_id="default_session", sample_rate=16000, num_channels=1, dtype=np.int16):

#     # 计算每次读取的字节数
#     sample_size = np.dtype(dtype).itemsize  # 每个样本的字节数
#     bytes_per_chunk = chunk_size * num_channels * sample_size

#     with open(file_path, 'rb') as f:
#         while True:
#             # 读取音频数据
#             pcm_data = f.read(bytes_per_chunk)
#             if not pcm_data:
#                 break  # 文件读取完毕

#             # 将字节数据转换为 numpy 数组
#             audio_data = np.frombuffer(pcm_data, dtype=dtype)

#             # 如果是多声道，转换为单声道
#             if num_channels > 1:
#                 audio_data = audio_data.reshape(-1, num_channels).mean(axis=1).astype(dtype)

#             # 生成 AudioChunk 消息
#             yield vad_pb2.AudioChunk(
#                 audio_data=audio_data.tobytes(),  # 转换为字节
#                 sample_rate=sample_rate,
#                 session_id=session_id
#             )


# def generate_audio_chunks(
#     file_path: str,
#     session_id: str = "default_session",
#     sample_rate: int = 16000,
#     num_channels: int = 1,
#     dtype: type = np.int16,
#     chunk_size: int = 1920,
# ):
   
#     # 参数校验
#     if not isinstance(file_path, str) or not file_path:
#         raise ValueError("file_path 必须是一个非空字符串。")
#     if sample_rate <= 0:
#         raise ValueError("sample_rate 必须大于 0。")
#     if num_channels <= 0:
#         raise ValueError("num_channels 必须大于 0。")
#     if chunk_size <= 0:
#         raise ValueError("chunk_size 必须大于 0。")

#     # 计算每次读取的字节数
#     sample_size = np.dtype(dtype).itemsize  # 每个样本的字节数
#     bytes_per_chunk = chunk_size * num_channels * sample_size

#     try:
#         with open(file_path, 'rb') as f:
#             logger.info(f"开始读取 PCM 文件: {file_path}")
#             while True:
#                 # 读取音频数据
#                 pcm_data = f.read(bytes_per_chunk)
#                 if not pcm_data:
#                     logger.info("PCM 文件读取完毕。")
#                     break  # 文件读取完毕

#                 # 将字节数据转换为 numpy 数组
#                 audio_data = np.frombuffer(pcm_data, dtype=dtype)

#                 # 如果是多声道，转换为单声道
#                 if num_channels > 1:
#                     audio_data = audio_data.reshape(-1, num_channels).mean(axis=1).astype(dtype)

#                 # 生成 AudioChunk 消息
#                 yield vad_pb2.AudioChunk(
#                     audio_data=audio_data.tobytes(),  # 转换为字节
#                     sample_rate=sample_rate,
#                     session_id=session_id
#                 )
#     except IOError as e:
#         logger.error(f"读取 PCM 文件失败: {e}")
#         raise
#     except Exception as e:
#         logger.error(f"生成音频块时发生错误: {e}")
#         raise

# def generate_audio_chunks(
#     file_path: str,
#     session_id: str = "default_session",
#     sample_rate: int = 16000,
#     num_channels: int = 1,
#     dtype: type = np.int16,
#     chunk_size: int = 1920,
# ) -> Generator[vad_pb2.AudioChunk, None, None]:
#     """
#     从 PCM 文件中生成音频块。

#     参数:
#         file_path (str): PCM 文件路径。
#         session_id (str): 会话 ID（默认 "default_session"）。
#         sample_rate (int): 采样率（默认 16000）。
#         num_channels (int): 声道数（默认 1）。
#         dtype (type): 音频数据类型（默认 np.int16）。
#         chunk_size (int): 每次读取的样本数（默认 1920）。

#     返回:
#         生成器，每次生成一个 AudioChunk 消息。

#     异常:
#         ValueError: 如果文件路径无效或参数不合法。
#         IOError: 如果文件读取失败。
#     """
#     # 参数校验
#     if not isinstance(file_path, str) or not file_path:
#         raise ValueError("file_path 必须是一个非空字符串。")
#     if sample_rate <= 0:
#         raise ValueError("sample_rate 必须大于 0。")
#     if num_channels <= 0:
#         raise ValueError("num_channels 必须大于 0。")
#     if chunk_size <= 0:
#         raise ValueError("chunk_size 必须大于 0。")

#     # 计算每次读取的字节数
#     sample_size = np.dtype(dtype).itemsize  # 每个样本的字节数
#     bytes_per_chunk = chunk_size * num_channels * sample_size

#     try:
#         with open(file_path, 'rb') as f:
#             logger.info(f"开始读取 PCM 文件: {file_path}")
#             while True:
#                 # 读取音频数据
#                 pcm_data = f.read(bytes_per_chunk)
#                 if not pcm_data:
#                     logger.info("PCM 文件读取完毕。")
#                     break  # 文件读取完毕

#                 # 将字节数据转换为 numpy 数组
#                 audio_data = np.frombuffer(pcm_data, dtype=dtype)

#                 # 如果是多声道，转换为单声道
#                 if num_channels > 1:
#                     audio_data = audio_data.reshape(-1, num_channels).mean(axis=1).astype(dtype)

#                 # 生成 AudioChunk 消息
#                 yield vad_pb2.AudioChunk(
#                     audio_data=audio_data.tobytes(),  # 转换为字节
#                     sample_rate=sample_rate,
#                     session_id=session_id
#                 )
#     except IOError as e:
#         logger.error(f"读取 PCM 文件失败: {e}")
#         raise
#     except Exception as e:
#         logger.error(f"生成音频块时发生错误: {e}")
#         raise
